home *** CD-ROM | disk | FTP | other *** search
/ The Very Best of Atari Inside / The Very Best of Atari Inside 1.iso / mint / mntlb20 / lib / _divsf3.cpp < prev    next >
C/C++ Source or Header  |  1992-03-30  |  5KB  |  231 lines

  1. #if !defined (__M68881__) && !defined (sfp004)
  2.  
  3. | single floating point divide routine
  4. |
  5. | written by Kai-Uwe Bloem (I5110401@dbstu1.bitnet).
  6. | Based on a 80x86 floating point packet from comp.os.minix, written by P.Housel
  7. |
  8. |
  9. | Revision 1.2, kub 01-90 :
  10. | added support for denormalized numbers
  11. |
  12. | Revision 1.1, kub 12-89 :
  13. | Created single float version for 68000
  14. |
  15. | Revision 1.0:
  16. | original 8088 code from P.S.Housel for double floats
  17.  
  18. BIAS4    =    0x7F-1
  19.  
  20.     .text
  21.     .even
  22.     .globl    __divsf3, ___divsf3
  23.     .globl    __infinitysf
  24.  
  25. #ifdef    ERROR_CHECK
  26. LC0:
  27.     .ascii "FLOATING POINT DIVISION by 0\12\15\0"
  28.     .even
  29. #endif    ERROR_CHECK
  30.  
  31. __divsf3:
  32. ___divsf3:
  33.  
  34. # ifdef    ERROR_CHECK
  35.     tstl    a7@(8)            | check if divisor is 0
  36.     bne    no_exception
  37.  
  38.     moveml    d0-d1,a7@-
  39.     pea    LC0
  40.     pea    __iob+52    |
  41.     jbsr    _fprintf    |
  42.     addql    #8,a7        |
  43.     moveml    a7@+,d0-d1
  44.                     | set _errno to ERANGE
  45. #  ifdef __MSHORT__
  46.     movew    #63,_errno
  47. #  else
  48.     movel    #63,_errno
  49. #  endif
  50.     movel    __infinitysf,d0        | return signed infinity 
  51.     btst    #31,a7@(4)        | transfer sign of dividend
  52.     beq    clear            | (mjr++)
  53.     bset    #31,d0            |
  54.     rts                |
  55. clear:                    |
  56.     rts
  57.  
  58. no_exception:
  59.  
  60. # endif    ERROR_CHECK
  61.  
  62.     lea    sp@(4),a0    | pointer to parameters u and v
  63.     moveml    d2-d5,sp@-    | save registers
  64.     moveml    a0@,d4/d5    | d4 = u, d5 = v
  65.  
  66.     movel    d4,d0        | d0 = u.exp
  67.     swap    d0
  68.     movew    d0,d2        | d2 = u.sign
  69.     lsrw    #7,d0
  70.     andw    #0xff,d0    | kill sign bit
  71.  
  72.     movel    d5,d1        | d1 = v.exp
  73.     swap    d1
  74.     eorw    d1,d2        | d2 = u.sign ^ v.sign (in bit 31)
  75.     lsrw    #7,d1
  76.     andw    #0xff,d1    | kill sign bit
  77.  
  78.     andl    #0x7fffff,d4    | remove exponent from u.mantissa
  79.     tstw    d0        | check for zero exponent - no leading "1"
  80.     beq    0f
  81.     orl    #0x800000,d4    | restore implied leading "1"
  82.     bra    1f
  83. 0:    addw    #1,d0        | "normalize" exponent
  84. 1:
  85. # ifndef ERROR_CHECK
  86.     tstl    d4
  87.     beq    retz        | dividing zero
  88. # endif    ERROR_CHECK
  89.  
  90.     andl    #0x7fffff,d5    | remove exponent from v.mantissa
  91.     tstw    d1        | check for zero exponent - no leading "1"
  92.     beq    0f
  93.     orl    #0x800000,d5    | restore implied leading "1"
  94.     bra    1f
  95. 0:    addw    #1,d1        | "normalize" exponent
  96. 1:    tstl    d5
  97.     beq    divz        | divide by zero
  98.  
  99.     subw    d1,d0        | subtract exponents,
  100.     addw    #BIAS4-8+1,d0    |  add bias back in, account for shift
  101.     addw    #34,d0        |  add loop offset, +2 for extra rounding bits
  102.                 |   for denormalized numbers (2 implied by dbra)
  103.     movew    #27,d1        | bit number for "implied" pos (+4 for rounding)
  104.     movel    #-1,d3        |  zero quotient (for speed a one''s complement)
  105.     subl    d5,d4        | initial subtraction, u = u - v
  106. 2:
  107.     btst    d1,d3        | divide until 1 in implied position
  108.     beq    5f
  109.  
  110.     addl    d4,d4
  111.     bcs    4f        | if carry is set, add, else subtract
  112.  
  113.     addxl    d3,d3        | shift quotient and set bit zero
  114.     subl    d5,d4        | subtract, u = u - v
  115.     dbra    d0,2b        | give up if result is denormalized
  116.     bra    5f
  117. 4:
  118.     addxl    d3,d3        | shift quotient and clear bit zero
  119.     addl    d5,d4        | add (restore), u = u + v
  120.     dbra    d0,2b        | give up if result is denormalized
  121. 5:    subw    #2,d0        | remove rounding offset for denormalized nums
  122.     notl    d3        | invert quotient to get it right
  123.  
  124.     movel    d3,d4        | save quotient mantissa
  125.     clrw    d1        | zero rounding bits
  126.     jmp    norm_sf        | (registers on stack removed by norm_sf)
  127.  
  128. # ifndef ERROR_CHECK
  129. retz:    clrl    d0        | zero destination
  130.     moveml    sp@+,d2-d5
  131.     rts            | no normalization needed
  132.  
  133. divz:    movel    __infinitysf,d0    | return infinity value
  134.     moveml    sp@+,d2-d5    | should really cause trap ?!?
  135.     btst    #31,sp@(4)    | transfer sign of dividend
  136.     beq    clear        | (mjr++)
  137.     bset    #31,d0        |
  138.     rts            |
  139. clear:                |
  140.     bclr    #31,d0        |
  141.     rts
  142. # endif    ERROR_CHECK
  143. #endif    /* !__M68881__ && !sfp004    */
  144. #ifdef    sfp004
  145.  
  146. | single precision floating point stuff for Atari-gcc using the SFP004
  147. | or compatible boards with a memory mapped 68881 
  148. | developed with gas
  149. |
  150. |  single floating point divide routine
  151. |
  152. | M. Ritzert (mjr at dmzrzu71)
  153. |            (ritzert@dfg.dbp.de)
  154. | 4.10.1990
  155. |
  156. | +_infinitysf returned instead of a NAN
  157. | the DOMAIN exception is not supported yet. In case of an exception
  158. | _errno is always set to ERANGE
  159.  
  160. | addresses of the 68881 data port. This choice is fastest when much data is
  161. | transferred between the two processors.
  162.  
  163. comm =     -6
  164. resp =    -16
  165. zahl =      0
  166.  
  167. | waiting loop ...
  168. |
  169. | wait:
  170. | ww:    cmpiw    #0x8900,a0@(resp)
  171. |     beq    ww
  172. | is coded directly by
  173. |    .long    0x0c688900, 0xfff067f8
  174.  
  175.  
  176.     .text
  177.     .even
  178.     .globl    __divsf3, ___divsf3
  179.  
  180. #ifdef    ERROR_CHECK
  181. LC0:
  182.     .ascii "FLOATING POINT DIVISION by 0\12\15\0"
  183.     .even
  184. #endif    ERROR_CHECK
  185.  
  186. __divsf3:
  187. ___divsf3:
  188.  
  189. #ifdef    ERROR_CHECK
  190.     tstl    a7@(8)            | check if divisor is 0
  191.     bne    no_exception
  192.  
  193.     moveml    d0-d7/a0-a6,a7@-    | print error message
  194.     pea    LC0
  195.     movew    #9,a7@-
  196.     trap    #1
  197.     addql    #6,a7
  198.     moveml    a7@+,d0-d7/a0-a6
  199.                     | set _errno to ERANGE
  200. #ifdef __MSHORT__
  201.     movew    #63,_errno
  202. #else
  203.     movel    #63,_errno
  204. #endif
  205.     movel    __infinitysf,d0        | return signed infinity 
  206.     btst    #31,a7@(4)        | transfer sign of dividend
  207.     beq    clear            | (mjr++)
  208.     bset    #31,d0            |
  209.     rts                |
  210. clear:                    |
  211.     bclr    #31,d0            |
  212.     rts
  213.  
  214. no_exception:
  215.  
  216. #endif    ERROR_CHECK
  217.  
  218.     lea    0xfffa50,a0
  219.     movew    #0x4400,a0@(comm)    | load first argument to fp0
  220.     cmpiw    #0x8900,a0@(resp)    | check
  221.     movel    a7@(4),a0@
  222.     movew    #0x4424,a0@(comm)
  223.     .long    0x0c688900, 0xfff067f8
  224.     movel    a7@(8),a0@
  225.     movew    #0x6400,a0@(comm)    | result to d0
  226.     .long    0x0c688900, 0xfff067f8
  227.     movel    a0@,d0            | REMARK: 0/0 returns a NAN
  228.     rts                | if ERROR_CHECK is disabled
  229.  
  230. #endif    sfp004
  231.